<?php

namespace Tyrone\Lib;

class Crontab
{
    private $jobs = [];
    private $timers = [];
    private $runNum = 1;
    private $runNumConfig = [];

    /**
     * 添加一个定时任务
     *
     * 支持类似 crontab 的格式（仅支持 * 和 数字）
     * 格式: "秒 分 时 日 月 周" （支持 *）
     * 例如:
     *   "* * * * *"        -> 每分钟
     *   "0 * * * *"        -> 每小时
     *   "0 0 * * *"        -> 每天零点
     *   "*\/5 * * * *"      -> 每 5 分钟（暂不支持 *）
     */
    public function add($spec, $callback,$replace=false)
    {
        $this->jobs[] = [
            'spec' => $spec,
            'callback' => $callback,
            'last_run' => 0,
        ];
        return $this;
    }

    public function setTask($tasks)
    {
        $this->jobs = $tasks;
        return $this;
    }
    public function getTaskCount()
    {
        return count($this->jobs);
    }

    public function setRunNum($list){
        $this->runNum = count($list);
        foreach ($list as $key => $config){
            $this->runNumConfig[$key] = $config;
        }
        return $this;
    }

    /**
     * 启动所有定时任务
     * 每秒检查一次是否应该执行
     */
    public function start()
    {
        // 每秒检查一次
        $tickId = \Swoole\Timer::tick(1000, function () {
            $now = time();
            $date = date('s i G j n w', $now); // 秒 分 时 日 月 周(0-6)
            $parts = explode(' ', $date);

            foreach ($this->jobs as $index => $job) {
                if ($this->shouldRun($job['spec'], $parts) && $now > $job['last_run']) {
                    // 标记已运行
                    $this->jobs[$index]['last_run'] = $now;
                    foreach($this->runNumConfig as $key => $config){

                        // 异步执行任务（避免阻塞 Timer）
                        \Swoole\Coroutine::create(function () use ($job,$key,$config) {
                            try {
                                call_user_func($job['callback'],$job,$key,$config);
                            } catch (\Throwable $e) {
                                echo "Crontab Job Error: " . $e->getMessage() . "\n";
                            }
                        });
                    }

                }
            }
        });
        return $tickId;
    }

    /**
     * 判断当前时间是否匹配任务
     */
    private function shouldRun($spec, $now): bool
    {
        $cron = preg_split('/\s+/', trim($spec));
        if(count($cron)==5) {
            $spec = '0 ' . $spec;
            $cron = preg_split('/\s+/', trim($spec));
        }
        if(count($cron) !== 6) {
            return false;
        }

        // 映射 cron 字段：秒 分 时 日 月 周
        $fieldNames = ['second', 'minute', 'hour', 'day', 'month', 'weekday'];

        foreach ($fieldNames as $i => $fieldName) {
            $cronPart = $cron[$i];
            $nowPart = (int)$now[$i]; // 当前时间的对应部分

            // 1. 如果是 '*'，匹配任意值
            if ($cronPart === '*') {
                continue;
            }

            // 2. 支持 */n 格式（如 */5）
            if (substr($cronPart, 0, 2) === '*/') {
                $step = (int) substr($cronPart, 2);
                if ($step <= 0) {
                    return false;
                }
                if ($nowPart % $step !== 0) {
                    return false;
                }
                continue;
            }

            // 3. 直接数字匹配
            if ((int)$cronPart !== $nowPart) {
                return false;
            }
        }

        return true;
    }
}